﻿using System;
using System.Collections.Generic;
using DataCenter.Share;

namespace DataCenter.Clr
{
    [Serializable]
    public abstract class AggregateStyle : ICloneable
    {
        public AggregateStyle(int FieldIndex)
        {
            this.FieldIndex = FieldIndex;
        }
        protected int FieldIndex;
        protected float ResultValue;

        public virtual float GetValue()
        {
            return ResultValue;
        }
        public abstract void Aggregate(ResultRecordRow row);

        public static AggregateStyle CreateInstance(string styleStr, string fieldName)
        {
            int FieldIndex;
            if (!int.TryParse(fieldName.Replace("R__", ""), out FieldIndex))
                throw new Exception("无效的字段名称" + fieldName);

            AggregateStyle style = null;
            switch (styleStr.Trim().ToUpper())
            {
                case "MAX": style = new MaxStyle(FieldIndex); break;
                case "MIN": style = new MinStyle(FieldIndex); break;
                case "AVG": style = new AvgStyle(FieldIndex); break;
                case "SUM": style = new SumStyle(FieldIndex); break;
                case "COUNT": style = new CountStyle(FieldIndex); break;
                default:
                    throw new InvalidOperationException("未知的统计类型" + styleStr);
            }
            return style;
        }

        #region ICloneable Members

        public object Clone()
        {
            return Utils.Clone(this);
        }

        #endregion
    }

    [Serializable]
    public class MinStyle : AggregateStyle
    {
        public MinStyle(int FieldIndex)
            : base(FieldIndex)
        {
            base.ResultValue = float.MaxValue;
        }

        public override void Aggregate(ResultRecordRow row)
        {
            float? rowValue = row.Values[FieldIndex];
            if (rowValue != null)
            {
                if (!float.IsNaN(rowValue.Value))
                {
                    if (rowValue.Value < ResultValue)
                        ResultValue = rowValue.Value;
                }
            }
        }
    }

    [Serializable]
    public class MaxStyle : AggregateStyle
    {
        public MaxStyle(int FieldIndex)
            : base(FieldIndex)
        {
            base.ResultValue = float.MinValue;
        }

        public override void Aggregate(ResultRecordRow row)
        {
            float? rowValue = row.Values[FieldIndex];
            if (rowValue != null)
            {
                if (!float.IsNaN(rowValue.Value))
                {
                    if (rowValue.Value > ResultValue)
                        ResultValue = rowValue.Value;
                }
            }
        }
    }

    [Serializable]
    public class SumStyle : AggregateStyle
    {
        public SumStyle(int FieldIndex)
            : base(FieldIndex)
        {
            base.ResultValue = 0.0f;
        }

        public override void Aggregate(ResultRecordRow row)
        {
            float? rowValue = row.Values[FieldIndex];
            if (rowValue != null)
            {
                if (!float.IsNaN(rowValue.Value))
                {
                    ResultValue += rowValue.Value;
                }
            }
        }
    }

    [Serializable]
    public class AvgStyle : AggregateStyle
    {
        public AvgStyle(int FieldIndex)
            : base(FieldIndex)
        {
            base.ResultValue = 0.0f;
        }        
        private int count;

        public override float GetValue()
        {
            if (count == 0) return 0.0f;
            return (base.ResultValue / count);
        }
        public override void Aggregate(ResultRecordRow row)
        {
            float? rowValue = row.Values[FieldIndex];
            if (rowValue != null)
            {
                if (!float.IsNaN(rowValue.Value))
                {
                    count += 1;
                    ResultValue += rowValue.Value;
                }
            }
        }
    }

    [Serializable]
    public class CountStyle : AggregateStyle
    {
        public CountStyle(int FieldIndex)
            : base(FieldIndex)
        {
            base.ResultValue = 0.0f;
        }

        public override void Aggregate(ResultRecordRow row)
        {
            float? rowValue = row.Values[FieldIndex];
            if (rowValue != null)
            {
                if (!float.IsNaN(rowValue.Value))
                {
                    ResultValue += 1;
                }
            }
        }
    }
}
